import modbus_tk
from singleton import singleton

import serial
from modbus_tk.exceptions import *
from modbus_tk import modbus_rtu
from Config import Config

@singleton
class ModbusManager(object):
    ser = serial.Serial()
    ser.baudrate = Config().inst().getint("modbus", "baudrate")
    # ser.port = "COM5"
    ser.port = Config().inst().get("modbus", "port")
    ser.timeout = Config().inst().getint("modbus", "timeout")
    ser.bytesize = Config().inst().getint("modbus", "bytesize")
    ser.parity = Config().inst().get("modbus", "parity")
    ser.stopbits = Config().inst().getint("modbus", "stopbits")
    ser.xonxoff = Config().inst().getint("modbus", "xonxoff")
    # master = modbus_rtu.RtuMaster(serial.Serial(port=port, baudrate=baudrate, bytesize=8, parity='N', stopbits=2, xonxoff=0))
    master = modbus_rtu.RtuMaster(ser)
    master.set_timeout(3.0)
    master.set_verbose(Config().inst().getboolean("modbus", "verbose"))

    logger = modbus_tk.utils.create_logger("console")

    def __init__(self):
        self.init()

    def init(self):
        try:
            # self.master = modbus_rtu.RtuMaster(serial.Serial(port="COM3", baudrate=115200, bytesize=8, parity='N', stopbits=2, xonxoff=0))
            self.ser.close()
            self.ser.open()
        except BaseException as e:
            print("SerialException {}".format(e))
        else:
            pass

    def get_master(self):
        return self.master

    def execute(self, slave, function_code, starting_address, quantity_of_x=0, output_value=0, data_format="", expected_length=-1):
        ret = None
        try:
            ret = self.master.execute(slave, function_code, starting_address, quantity_of_x, output_value=output_value)
        except ModbusFunctionNotSupportedError as e:
            print("ModbusInvalidResponseError {}".format(e))
        except DuplicatedKeyError as e:
            print("ModbusInvalidResponseError {}".format(e))
        except MissingKeyError as e:
            print("ModbusInvalidResponseError {}".format(e))
        except InvalidModbusBlockError as e:
            print("ModbusInvalidResponseError {}".format(e))
        except InvalidArgumentError as e:
            print("ModbusInvalidResponseError {}".format(e))
        except OverlapModbusBlockError as e:
            print("ModbusInvalidResponseError {}".format(e))
        except OutOfModbusBlockError as e:
            print("ModbusInvalidResponseError {}".format(e))
        except ModbusInvalidResponseError as e:
            print("ModbusInvalidResponseError {}".format(e))
        except ModbusInvalidRequestError as e:
            print("ModbusInvalidResponseError {}".format(e))
        except ModbusError as e:
            print("ModbusError".format(e))
        except Exception as e:
            print("BaseException {}".format(e))
        finally:
            return ret
